<script setup>
import {onMounted, ref} from "vue";
import {add, edit, listById, allTree, deleteById} from "@/api/system/menu.js"
import { ElMessageBox } from 'element-plus'
import IconSelector from "@/components/common/icon-selector.vue";
import path from "path";

defineOptions({
  name: '/system/menu'
})

//搜索
const search = ref({
  name: "",
  status: ""
})

const props = {
  label: 'name',
}

//状态枚举
const statusEnums = ref([
  {label: '启用', value: 1},
  {label: '停用', value: 2},
])

//显示枚举
const visibleEnums = ref([
  {label: '隐藏', value: 0},
  {label: '显示', value: 1}
])

//菜单类型
const menuTypeEnum = ref([
  {label: '目录', value: 1},
  {label: '菜单', value: 2},
  {label: '按钮', value: 3}
])

//搜索表单实例
const searchFormRef = ref(null)

//Dialog配置
const dialogConfig = ref({
  visible: false,
  title: "添加",
  closeOnClickModal: false
})

//菜单实体
const menu = ref({
  id: "",
  pid: "",
  name: "",
  type: 1,
  status: 1,
  sort: '',
  path: "",
  icon: "",
  visible: 1,
  component: "",
  permission: "",
  createTime: "",
  updateTime: ""
})

const iconDialogVisible = ref(false)

//菜单集合
const menuData = ref([])
const treeSelectData = ref([])

const validatePermission = (rule, value, callback) => {
  if (menu.value.type === 3 && value === '') {
    callback(new Error('权限标识不能为空'))
  } else {
    callback()
  }
}

const validatePath = (rule, value, callback) => {
  if (menu.value.type === 1 || form.value.type === 2) {
    if (value === '') {
      callback(new Error('路由地址不能为空'))
    }
  } else {
    callback()
  }
}

const validateComponent = (rule, value, callback) => {
  if (menu.value.type === 2 && value === '') {
    callback(new Error('组件地址不能为空'))
  } else {
    callback()
  }
}

const rules = ref({
  pid: [
    {required: true, message: '节点不能为空', trigger: 'change'}
  ],
  name: [
    {required: true, message: '名称不能为空', trigger: 'blur'}
  ],
  path: [
      {validator: validatePath, trigger: 'blur'}
  ],
  component: [
    {validator: validateComponent, trigger: 'blur'}
  ],
  permission: [
    {validator: validatePermission, trigger: 'blur'}
  ]
})

const form = ref(null)

/**
 * 监听重置事件
 */
const onReset = () => {
  searchFormRef.value.resetFields()
}

/**
 * 监听搜索事件
 */
const onSearch = () => {
}

/**
 * 监听添加事件
 */
const onAdd = () => {
  dialogConfig.value.visible = true
  dialogConfig.value.title = "添加"
}

/**
 * 处理Dialog关闭后的回调事件
 */
const handleDialogClosed = () => {
  menu.value = {
    id: "",
    pid: "",
    name: "",
    type: 1,
    status: 1,
    sort: '',
    path: "",
    icon: "",
    visible: 1,
    component: "",
    permission: "",
    createTime: "",
    updateTime: ""
  }
  if (!form.value) return
  form.value.resetFields()
}

/**
 * 监听Dialog确认事件
 */
const onDialogConfirm = async () => {
  if (!form.value) return
  const valid = await form.value.validate()
  if (valid) {
    if (menu.value.id > 0) {
      await edit(menu.value)
    } else {
      await add(menu.value)
    }
  }
  requestAllTree()
  dialogConfig.value.visible = false
}

const requestAllTree = () => {
  allTree().then(resp => {
    menuData.value = [...resp.data]
    treeSelectData.value = [{id: '0', name: '根节点', children: [...resp.data]}]
  })
}

/**
 * 计算Type的文本信息
 * @param rowData
 */
const computeTypeText = (rowData) => {
  const type = rowData.target.type
  return  menuTypeEnum.value.reduce((init, next) => {
    if (type === next.value) {
      init = next.label
    }

    return init
  }, "")
}

/**
 * 处理新增事件
 * @param rowData
 */
const handleAdd = (rowData) => {
  menu.value = {
    id: "",
    pid: rowData.id,
    name: "",
    type: 1,
    status: 1,
    sort: '',
    path: "",
    icon: "",
    visible: 1,
    component: "",
    permission: "",
    createTime: "",
    updateTime: ""
  }
  dialogConfig.value.visible = true
}

/**
 * 处理编辑事件
 * @param rowData
 */
const handleEdit = (rowData) => {
  menu.value = {...rowData}
  dialogConfig.value.visible = true
}

/**
 * 初始删除事件
 * @param rowData
 */
const handleDelete = (rowData) => {
  ElMessageBox.confirm('是否确认删除这个节点数据?', '提示', {
    cancelButtonText: '取消',
    confirmButtonText: '确认'
  }).then(() => {
    deleteById(rowData.id).then(() => {
      requestAllTree()
    })
  })
}

/**
 * 挂载后初始化工作
 */
onMounted(() => {
  requestAllTree()
})

//图标选择事件
const onIconSelect = (icon) => {
  menu.value.icon = icon.name
  iconDialogVisible.value = false
}
</script>

<template>
  <div class="cb-main-container">
<!--    <div class="search-box cb-common-box">-->
<!--      <el-form inline :model="search" ref="searchFormRef">-->
<!--        <el-form-item prop="name" label="名称">-->
<!--          <el-input v-model="search.name" placeholder="请输入菜单名称"></el-input>-->
<!--        </el-form-item>-->
<!--        <el-form-item prop="status" label="状态" style="width:210px">-->
<!--          <el-select v-model="search.status" placeholder="请选择菜单状态">-->
<!--            <el-option v-for="(item, index) in statusEnums" :key="index" :label="item.label" :value="item.value" />-->
<!--          </el-select>-->
<!--        </el-form-item>-->
<!--        <el-form-item>-->
<!--          <el-button :icon="Refresh" @click="onReset">重置</el-button>-->
<!--          <el-button type="primary" :icon="Search" @click="onSearch">搜索</el-button>-->
<!--        </el-form-item>-->
<!--      </el-form>-->
<!--    </div>-->
    <div class="main-box cb-common-box">
      <div>
        <el-button type="primary" icon="Plus" @click="onAdd()">新增</el-button>
      </div>
      <el-table :data="menuData" class="cb-table-box" empty-text="暂无数据" size="large" row-key="id">
        <el-table-column prop="name" label="名称" class-name="menuData-name">
          <template #default="scope">
            <div style="display: flex; flex-direction: row; align-items: center">
              <el-icon :size="23" v-if="scope.row.target.icon">
                <component :is="scope.row.target.icon" />
              </el-icon>
              <span style="display: inline-block; margin-left: 4px">{{ scope.row.target.name }}</span>
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="type" label="类型">
          <template #default="scope">
            <el-tag type="primary" effect="dark">{{ computeTypeText(scope.row) }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="visible" label="显示">
          <template #default="scope">
            <el-tag :type="scope.row.target.visible === 1 ? 'primary' : 'info'" effect="dark">{{ scope.row.target.visible === 1 ? '显示' : '隐藏' }}{{}}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="target.sort" label="排序" />
        <el-table-column prop="status" label="状态">
          <template #default="scope">
            <el-tag :type="scope.row.target.status === 1 ? 'primary' : 'info'">{{ scope.row.target.status === 1 ? '启用' : '禁用' }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column align="right" label="操作">
          <template #default="scope">
            <el-button v-if="scope.row.target.type !== 3" type="primary" link @click="handleAdd(scope.row.target)" icon="Plus">新增</el-button>
            <el-button type="primary" link @click="handleEdit(scope.row.target)" icon="Edit">编辑</el-button>
            <el-button link type="danger" @click="handleDelete(scope.row.target)" icon="Delete">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>

    <!-- 添加/编辑区域S -->
    <el-dialog v-model="dialogConfig.visible" :title="dialogConfig.title" width="500" :close-on-click-modal="dialogConfig.closeOnClickModal" @closed="handleDialogClosed">
      <el-form :model="menu" label-width="86px" :rules="rules" ref="form">
        <el-form-item label="所属菜单" prop="pid">
          <el-tree-select
              :check-strictly=true
              node-key="id"
              placeholder="请选择所属菜单，默认顶级菜单"
              v-model="menu.pid"
              :data="treeSelectData"
              :props="props"
              :render-after-expand="false"
              no-data-text="暂无数据"
          />
        </el-form-item>
        <el-form-item label="类型" prop="type">
          <el-radio-group v-model="menu.type">
            <el-radio-button v-for="(item, index) in menuTypeEnum" :key="index" :label="item.label" :value="item.value" />
          </el-radio-group>
        </el-form-item>
        <el-form-item label="名称" prop="name">
          <div style="display: flex; align-items: center;">
            <el-input style="flex: 1; margin-right: 10px;" v-model="menu.name" autocomplete="off" placeholder="请输入菜单名称" :prefix-icon="menu.icon" />
            <el-button @click="iconDialogVisible = true">图标</el-button>
          </div>
        </el-form-item>
        <el-form-item label="路由" prop="route" v-if="menu.type === 1">
          <el-input v-model="menu.path" placeholder="请输入路由地址" />
        </el-form-item>
        <el-form-item label="权限标识" prop="permission" v-if="menu.type === 3">
          <el-input v-model="menu.permission" placeholder="请输入权限标识" />
        </el-form-item>
        <el-row v-if="menu.type === 2">
          <el-col :span="12">
            <el-form-item label="路由" prop="path">
              <el-input v-model="menu.path" placeholder="请输入路由地址" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="组件" prop="component">
              <el-input v-model="menu.component" placeholder="请输入组件地址" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="菜单状态">
              <el-select v-model="menu.status" placeholder="请选择菜单状态">
                <el-option v-for="(item, index) in statusEnums" :label="item.label" :value="item.value" :key="index" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="显示状态" prop="visible">
              <el-select v-model="menu.visible" placeholder="请选择显示状态">
                <el-option v-for="(item, index) in visibleEnums" :label="item.label" :value="item.value" :key="index" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="排序" prop="sort">
              <el-input v-model="menu.sort" autocomplete="off" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="dialogConfig.visible = false">取消</el-button>
          <el-button type="primary" @click="onDialogConfirm">确认</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 添加/编辑区域E -->

    <!-- Icon选择器S -->
    <icon-selector v-model:visible="iconDialogVisible" @select="onIconSelect" />
    <!-- Icon选择器E -->
  </div>
</template>

<style scoped lang="scss">
.cb-main-container {
  flex-direction: column;

  .main-box {
    overflow: scroll;
  }

  :deep(.menuData-name .cell) {
    display: flex;
    flex-direction: row;
    align-items: center;
  }
}
</style>
